package server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import model.CustomerImpl;
import model.OrderImpl;
import model.ProductImpl;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Transactional;

import stub.Product;
import stub.Warehouse;
import dao.CustomerDao;
import dao.OrderDao;
import dao.ProductDao;


public class WarehouseImpl extends UnicastRemoteObject implements Warehouse{
	
	private CustomerDao	customerDao;
	private OrderDao	orderDao;
	private ProductDao	productDao;
	
	
	public WarehouseImpl() throws RemoteException {
		ApplicationContext appContext = new ClassPathXmlApplicationContext( "config/spring-configuration.xml" );
		orderDao = ( OrderDao ) appContext.getBean( "orderDao" );
		productDao = ( ProductDao ) appContext.getBean( "productDao" );
		
		// Add products
		productDao.addProduct( new ProductImpl( "Fiets", "algemeen", 10.99 ) );
		productDao.addProduct( new ProductImpl( "auto", "algemeen", 130.99 ) );
		productDao.addProduct( new ProductImpl( "geluidsinstallatie", "electronica", 300.99 ) );
		productDao.addProduct( new ProductImpl( "laptop", "electronica", 600.99 ) );
		productDao.addProduct( new ProductImpl( "eten", "eten", 2.99 ) );
	}
	
	@Override
	public List<Product> getProducten() throws RemoteException {
		return productDao.getProducts();
	}
	
	
	@Override
	public List<String> getProductTypes() throws RemoteException {
		List<String> types = new ArrayList<String>();
		for( Product p : productDao.getProducts() ){
			if( !types.contains( p.getType() ) ){
				types.add( p.getType() );
			}
		}
		return types;
	}
	
	
	@Override
	public ArrayList<Product> getProducten( String type ) throws RemoteException {
		ArrayList<Product> productMatches = new ArrayList<Product>();
		for( Product p : productDao.getProducts() ){
			if( p.getType().equals( type ) ){
				productMatches.add( p );
			}
		}
		return productMatches;
	}
	
	@Transactional()
	@Override
	public synchronized Long newOrder( String customerName ) throws RemoteException {
		return orderDao.addOrder( new OrderImpl( new CustomerImpl(customerName) ) );
	}
	
	@Transactional()
	@Override
	public boolean order( String customerName, Long orderNr, String productName, int amount ) throws RemoteException {
		OrderImpl order = orderDao.getOrder( orderNr );
		order.addProduct( ( ProductImpl ) findProductByName( productName ), amount );
		orderDao.update( order );
		return true;
	}
	
	
	public Product findProductByName( String productName ) throws RemoteException {
		Product foundProduct = null;
		for( Product p : productDao.getProducts() ){
			if( p.getName().equals( productName ) ){
				foundProduct = p;
				break;
			}
		}
		return foundProduct;
	}
	
	
	public List<OrderImpl> getOrders() {
		return orderDao.getOrders();
	}
	
	
	@Override
	public Map<Product, Integer> getOrderOverview( String customerName, Long orderNr ) throws RemoteException {
		Map<Product, Integer> map = new HashMap<Product, Integer>();
		OrderImpl order = orderDao.getOrder( orderNr );
		
		for( ProductImpl p : order.getProductsOverview().keySet() ){
			Integer amount = order.getProductsOverview().get( p );
			map.put( p, amount );
		}
		return map;
	}
	
	
	@Override
	public double getTotalPriceForOrder( String customerName, Long orderNr ) throws RemoteException {
		return orderDao.getOrder( orderNr ).getTotalPrice();
	}
	
	@Transactional()
	@Override
	public boolean secureOrder( String customerName, Long orderNr ) throws RemoteException {
		OrderImpl order = orderDao.getOrder( orderNr );
		order.orderSecured();
		orderDao.update( order );
		return true;
	}
	
}
